package dai.samples.batch.rollback;

import dai.samples.batch.config.DbWriter;
import dai.samples.batch.entity.BatchEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.json.JacksonJsonObjectReader;
import org.springframework.batch.item.json.builder.JsonItemReaderBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.PlatformTransactionManager;

import java.util.UUID;

/**
 * Step可以使用不应导致回滚的异常列表来配置
 * @author daify
 * @date 2020-11-15
 */
@Slf4j
@Configuration
public class RollBackJobConfig {

    @Autowired
    JobBuilderFactory jobBuilderFactory;

    @Autowired
    StepBuilderFactory stepBuilderFactory;

    @Autowired
    PlatformTransactionManager transactionManager;

    @Autowired
    DbWriter dbWriter;

    /***
     * 不配置例外回滚时候的操作
     * @param jobRepository
     * @return
     */
    @Bean("rollBackJob")
    public Job rollBackJob(JobRepository jobRepository) {
        return this.jobBuilderFactory.get("rollBackJob")
                .repository(jobRepository)
                .start(rollBackStep())
                .build();
    }

    /**
     * 配置例外回滚后的操作
     * @param jobRepository
     * @return
     */
    @Bean("rollBackErrorJob")
    public Job rollBackErrorJob(JobRepository jobRepository) {
        return this.jobBuilderFactory.get("rollBackErrorJob")
                .repository(jobRepository)
                .start(rollBackErrorStep())
                .build();
    }

    /**
     * 遇见RuntimeException异常不进行事务回滚
     * @return
     */
    @Bean("rollBackStep")
    public Step rollBackStep() {
        return this.stepBuilderFactory.get("rollBackStep")
                .<BatchEntity, BatchEntity>chunk(4)
                .reader(itemReader())
                .processor(getProcessor())
                .writer(dbWriter)
                .build();
    }


    /**
     * 遇见RuntimeException异常不进行事务回滚
     * @return
     */
    @Bean("rollBackErrorStep")
    public Step rollBackErrorStep() {
        return this.stepBuilderFactory.get("rollBackErrorStep")
                .<BatchEntity, BatchEntity>chunk(4)
                .reader(itemReader())
                .processor(getProcessor())
                .writer(dbWriter)
                .faultTolerant()
                .noRollback(RuntimeException.class)
                .build();
    }

    /**
     * JSON读数据
     * @return
     */
    public ItemReader<BatchEntity> itemReader() {
        return new JsonItemReaderBuilder<BatchEntity>()
                .jsonObjectReader(new JacksonJsonObjectReader<>(BatchEntity.class))
                .resource(new ClassPathResource("data/batchJob.json"))
                .name("batchJobReader")
                .build();
    }

    public ItemProcessor<? super BatchEntity, ? extends BatchEntity> getProcessor() {
        return new ChangeNameProcessor();
    }



    /**
     * 处理过程
     */
    class ChangeNameProcessor implements ItemProcessor<BatchEntity, BatchEntity> {

        @Override
        public BatchEntity process(BatchEntity person) {
            String fullName = person.getFirstName() + " " +
                    person.getLastName();
            String id = UUID.randomUUID().toString();
            person.setEntityId(id);
            person.setFullName(fullName);
            System.out.println(fullName + ":" + person.getAge());
            if (person.getAge() > 10) {
                throw new RuntimeException();
            }
            return person;
        }
    }

}
